<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<pre>
		JavaScript 命名空间
使用过Java、C#的同学对命名空间非常的熟悉，在复杂的系统中会有N多的函数、对象，语言提供的、架构预定义的，这么多的函数和对象，由于编程规范要求起有实际意义的名字，难免会重名发生错误调用，而有了命名空间烦恼就没有了，不但可以分类组织函数与对象，还可以形成隔离，解决重名问题。

使用JavaScript就没有这么舒服了，Javascript只有函数作用域，什么块儿啊、神马文件啊统统都认为是一个命名空间的，有时候因为一些重名问题导致的错误让人莫名其妙，难以调试解决。

一个简单的例子
复制代码
<input type="button" value="test" onclick="alert();"/>
        
        <script type="text/javascript">
            function alert(){
                //.......
                
                test2();
                //.......
            }
            
            function test2(){
                alert('test2')
            }
复制代码
在个例子在不同的浏览器下有不同表现，IE会报Stack over flow, Firefox会死掉。。。反正都会报错，很简单的错误，代码中自定义了一个alert函数，在alert函数中调用了test2函数，test2函数中意图调用window的alert方法，这样循环调用了，也许看了你会说这么明显的错误谁会犯，但是如果自定义的方法叫close（这个经常会出现吧），然后内部调用了一个外部文件的函数，该函数调用了window的close方法，这样错误是不是隐蔽了很多呢。

简单的命名空间
由于JavaScript没有文件作用域，不同的函数分散在不同的文件中，甚至由不同的人编写，重名的概率大大增加。是不是足够小心就可以了呢？也不尽然，还有些意外情况，比如经常会用到继承，于是写了一个没出现过的函数名extend，不料在EcmaScript5中加入了extend函数，命名空间的必要性就体现出来了。

JavaScript有函数的作用域，可以利用这点把自定义的函数写到一个函数体内，这样函数内的变量、对象、函数就像在一个命名空间内一样和外部隔离。

复制代码
<input type="button" value="test" onclick="(new namespace()).alert();"/>
        
        <script type="text/javascript">
            function namespace(){
                this.alert=function(){
                    console.log('test');
                }
            }
        </script>
复制代码
这样自定义的alert方法就不会和window的alert冲突了。

简单进化
这样可以是可以，但也有问题，最大的问题在于调用方式复杂而丑陋！每次调用的时候都要实例化对象，然后调用其方法，简单修改代码让其实现自动实例化。

复制代码
<input type="button" value="test" onclick="NS.alert();"/>
        
        <script type="text/javascript">
            (function namespace(){
                this.alert=function(){
                    console.log('test');
                }
                
                window.NS=this;
            })();
        </script>
复制代码
要看明白上面代码首先要了解一下“立即执行函数”（江湖人是这么称呼的）的技巧结构类似这样

(function xxx(){

       //function body 

 })();
这样写xxx函数就可以在定义完后自动执行，看起来神奇，其实上面写法可以拆成这样

复制代码
function xxx(){

       //function body 

 }

xxx();
复制代码
就是定义一个函数，然后使用括号语法调用，而函数定义外面的一层括号只起到将函数声明转为函数定义表达式，因为只有表达式才可以使用括号调用。看明白这些妖蛾子之后上面代码就简单了，在自定义namespace函数最后把this赋值为window的NS属性，在调用的时候直接使用NS.xx就可以了。看起来好了很多。

美化一下
上面的写法看起来不错了，但是函数名namespace貌似是多余的了，可以美化一下

复制代码
(function (){
                this.alert=function(){
                    console.log('test');
                }
                
                window.NS=this;
            })();
复制代码
变成了一个立即执行的匿名函数，美化了一些，不过看起来还是怪怪的，对呀，明明是实例化的function，为什么方法定义不写到prototype中呢，匿名函数怎么写prototype。。。，还得动动脑筋

复制代码
(function(){
                var _NS=function(){
                
                }
                _NS.prototype.alert=function(){
                    console.log('test');
                }
                window.NS=new _NS();
            })();
复制代码
 

写几个有用的函数
querySelector和querySelectorAll是W3C提供的新的查询接口，但是名字好长，自己写个简单的，innerHTML属性也常用到，写个简单版仿jQuery的html方法

复制代码
(function () {
            var _NS = function () {
              
            }
         
            _NS.prototype.select = function (selector,context) {
                var context = context || document;
                return context.querySelectorAll(selector);
            }

            _NS.prototype.isArrayLike=function(obj){
                if(obj instanceof Array){
                    return true;
                }

                var length=obj.length;
                if ( obj.nodeType === 1 && length ) {
                    return true;
                }
                return false;
            }

            _NS.prototype.html = function (obj,value) {
                var isArray=this.isArrayLike(obj), i=0;

                if (typeof value == 'string') {
                    if (!isArray) {
                        obj.innerHTML = value;
                    } else {
                        var length = obj.length;
                        while (i < length) {
                            obj[i].innerHTML = value;
                            i += 1;
                        }
                    }
                } else {
                    if (!isArray) {
                        return obj.innerHTML;
                    } else {
                        return obj[0].innerHTML;
                    }
                }
            }

            window.NS = new _NS();
        })();
复制代码
这样一个带有命名空间的简单JavaScript库就写成了，不用担心命名冲突了，但是用起来很不方便啊，做前端的同学都用过jQuery，人家用起来那叫一个简单,jQuery是怎么做的？欲知后事如何，且听下回分解。
分类: JavaScript Core
	</pre>
</body>
</html>